#Copyright (c) 2010 Intel Coprporation
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.

import re
 
preString = """; This file is generated by generate_64b_asm_stubs.py script.
; Do not modify. For more comments refer to generator script.
.code 
EXTERN wrapperIndex : QWORD
EXTERN extFunctions : QWORD

WrapperLogFunctionPre PROTO
WrapperLogFunctionPost PROTO

"""

postString = """
END"""

tplString = """
WrapperCall<n> PROC

;Save the return address pointer
mov rax, QWORD PTR [rsp]

;Move the stack pointer back to the dead space padding stored on Win64
; (8 bytes for ret address, 32 for dead space)
add rsp, 40

;Save the registers (integer/float pairs)
;  (Could save and restore using direct moves as below, but that seems to generate larger code - but 10 fewer instructions?)
;  movq QWORD PTR [rsp + 8], xmm0
;  mov QWORD PTR [rsp + 0], rcx
;
;  mov rcx, QWORD PTR [rsp + 0]
;  movq xmm0, QWORD PTR [rsp + 8]
;

push r9
movd r9, xmm3
push r9

push r8
movd r8, xmm2
push r8

push rdx
movd rdx, xmm1
push rdx

push rcx
movd rcx, xmm0
push rcx

; Move the wrapper index as the first parameter and
; the return address as the second parameter
; the parameter stack position data is the third parameter
mov ecx, DWORD PTR [wrapperIndex+<n>*4]
mov rdx, rax
mov r8, rsp

;Add the dead space for calling the function
sub rsp, 32
call WrapperLogFunctionPre
add rsp, 32

; Restore the registers
pop rcx
movd xmm0, rcx
pop rcx

pop rdx
movd xmm1, rdx
pop rdx

pop r8
movd xmm2, r8
pop r8

pop r9
movd xmm3, r9
pop r9

;Move the stack pointer back to the dead space padding stored on Win64
sub rsp, 32

;Make the function call (preserve rax for return value)
mov rax, QWORD PTR [extFunctions+<n>*8]
call rax

;Remove the dead space for calling the function?
add rsp, 32

; Save the return data
push rax

; Move the wrapper index as the first parameter and
; the return value as the second parameter
mov ecx, DWORD PTR [wrapperIndex+<n>*4]
mov rdx, rax

;Move the stack pointer back to the dead space padding stored on Win64
; (32 for dead space + 8 bytes for 16 byte alignment of stack)
sub rsp, 40
call WrapperLogFunctionPost
add rsp, 40

; Restore the return value
pop rcx
sub rsp, 32

; Push the old return address to the stack
push rax

; Restore the GL return value to rax and return
mov rax, rcx

ret

WrapperCall<n> ENDP
"""
file = open("ExtensionFunctionStubs_64.asm", "w")
file.write(preString)
for n in range(0,2000):
	working_string = tplString.replace("<n>", str(n))
	file.write( re.sub(";.*\n","",working_string) )
file.write(postString)
file.close()
